package es.uned.etsii.si3.taller.servlets;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.j256.ormlite.stmt.QueryBuilder;
import com.opensymphony.xwork2.ActionSupport;

import es.uned.etsii.si3.taller.Cliente;
import es.uned.etsii.si3.taller.FactoriaDAO;
import es.uned.etsii.si3.taller.ParteTrabajo;
import es.uned.etsii.si3.taller.Reparacion;
import es.uned.etsii.si3.taller.Vehiculo;

public class AdminListadoReparaciones extends ActionSupport {
	private static final long serialVersionUID = 1L;
	
	private Cliente cliente = null;
	private Vehiculo vehiculo = null;
	private int idCliente = 0;
	private int idVehiculo = 0;
	List<InfoReparacionClientes> listaReparacionesPendientesCliente;
	List<InfoReparacionClientes> listaReparacionesVistoBuenoCliente;
	List<InfoReparacionVehiculos> listaReparacionesPendientesVehiculo;
	List<InfoReparacionVehiculos> listaReparacionesVistoBuenoVehiculo;
	
	// Esto es sólo para guardar información si hubo errores al seleccionar cliente
	
	private class InfoReparacion {
		private Reparacion reparacion;
		
		public Reparacion getReparacion() {
			return reparacion;
		}
		
		public void setReparacion(Reparacion reparacion) {
			this.reparacion = reparacion;
		}
	}
	
	public class InfoReparacionClientes extends InfoReparacion {
		private Vehiculo vehiculo;
		
		public Vehiculo getVehiculo() {
			return vehiculo;
		}
		
		public void setVehiculo(Vehiculo vehiculo) {
			this.vehiculo = vehiculo;
		}
	}
	
	public class InfoReparacionVehiculos extends InfoReparacion {
		private Cliente cliente;
		
		public Cliente getCliente() {
			return cliente;
		}
		
		public void setCliente(Cliente cliente) {
			this.cliente = cliente;
		}
	}
	
	/* BEGIN: setters y getters */
	
	public void setClienteEscogido(int idCliente) {
		this.idCliente = idCliente;
	}
	
	public void setVehiculoEscogido(int idVehiculo) {
		this.idVehiculo = idVehiculo;
	}
	
	public Cliente getCliente() {
		return cliente;
	}
	
	public Vehiculo getVehiculo() {
		return vehiculo;
	}
	
	public List<InfoReparacionClientes> getListaReparacionesPendientesCliente() {
		return listaReparacionesPendientesCliente;
	}
	
	private void setListaReparacionesPendientesCliente(List<InfoReparacionClientes> lista) {
		listaReparacionesPendientesCliente = lista;
	}
	
	public List<InfoReparacionClientes> getListaReparacionesVistoBuenoCliente() {
		return listaReparacionesVistoBuenoCliente;
	}
	
	private void setListaReparacionesVistoBuenoCliente(List<InfoReparacionClientes> lista) {
		listaReparacionesVistoBuenoCliente = lista;
	}
	
	public List<InfoReparacionVehiculos> getListaReparacionesPendientesVehiculo() {
		return listaReparacionesPendientesVehiculo;
	}
	
	private void setListaReparacionesPendientesVehiculo(List<InfoReparacionVehiculos> lista) {
		listaReparacionesPendientesVehiculo = lista;
	}
	
	public List<InfoReparacionVehiculos> getListaReparacionesVistoBuenoVehiculo() {
		return listaReparacionesVistoBuenoVehiculo;
	}
	
	private void setListaReparacionesVistoBuenoVehiculo(List<InfoReparacionVehiculos> lista) {
		listaReparacionesVistoBuenoVehiculo = lista;
	}
	/* END: setters y getters */

	/**
	 * Valida que los datos introducidos para la búsqueda son correctos
	 */
	@Override
	public void validate() {
		if ((idCliente == 0) && (idVehiculo == 0)) {
			addActionError("No se ha seleccionado nada");
			return;
		}
		
		if (idCliente != 0) {
			if (idCliente > 0) {
				try {
					cliente = FactoriaDAO.recuperar(Cliente.class, idCliente);
				} catch (SQLException e) {
					addActionError("Error al intentar recuperar el cliente: " +  e.toString());
				}
			}
			else {
				addActionError("El identificador de cliente está fuera de rango");
			}
		}
		else if (idVehiculo != 0) {
			if (idVehiculo > 0) {
				try {
					vehiculo = FactoriaDAO.recuperar(Vehiculo.class, idVehiculo);
				} catch (SQLException e) {
					addActionError("Error al intentar recuperar el vehículo: " +  e.toString());
				}
			}
			else {
				addActionError("El identificador de vehículo está fuera de rango");
			}
		}
	}
	
	private void setReparacionesCliente(Cliente filtro) throws SQLException {
		QueryBuilder<ParteTrabajo, Integer> parteQb = FactoriaDAO.getQueryBuilder(ParteTrabajo.class);
		QueryBuilder<Reparacion, Integer> reparacionQb = FactoriaDAO.getQueryBuilder(Reparacion.class);
		
		parteQb.selectColumns(ParteTrabajo.ID_FIELD_NAME);
		parteQb.where().eq(ParteTrabajo.ID_USUARIO_FIELD_NAME, filtro.getUsuario());
		parteQb.orderBy(ParteTrabajo.FECHAENTRADA_FIELD_NAME, false);
		
		reparacionQb.join(parteQb);
		
		List<InfoReparacionClientes> listaPendientes = new ArrayList<InfoReparacionClientes>();		
		List<InfoReparacionClientes> listaVistoBueno = new ArrayList<InfoReparacionClientes>();		
		for (Reparacion reparacion: reparacionQb.query()) {
			InfoReparacionClientes info = new InfoReparacionClientes();
			
			info.setReparacion(reparacion);
			info.setVehiculo(reparacion.getParteTrabajo().getVehiculo());
			
			if (reparacion.getVistoBueno())
				listaVistoBueno.add(info);
			else
				listaPendientes.add(info);
		}
		
		setListaReparacionesPendientesCliente(listaPendientes);
		setListaReparacionesVistoBuenoCliente(listaVistoBueno);
	}
	

	private void setReparacionesVehiculo(Vehiculo filtro) throws SQLException {
		QueryBuilder<ParteTrabajo, Integer> parteQb = FactoriaDAO.getQueryBuilder(ParteTrabajo.class);
		QueryBuilder<Reparacion, Integer> reparacionQb = FactoriaDAO.getQueryBuilder(Reparacion.class);
		
		parteQb.selectColumns(ParteTrabajo.ID_FIELD_NAME);
		parteQb.where().eq(ParteTrabajo.ID_VEHICULO_FIELD_NAME, filtro);
		parteQb.orderBy(ParteTrabajo.FECHAENTRADA_FIELD_NAME, false);
		
		reparacionQb.join(parteQb);
		
		List<InfoReparacionVehiculos> listaPendientes = new ArrayList<InfoReparacionVehiculos>();		
		List<InfoReparacionVehiculos> listaVistoBueno = new ArrayList<InfoReparacionVehiculos>();		
		for (Reparacion reparacion: reparacionQb.query()) {
			InfoReparacionVehiculos info = new InfoReparacionVehiculos();
			
			info.setReparacion(reparacion);
			info.setCliente(reparacion.getParteTrabajo().getUsuario().getCliente());
			
			if (reparacion.getVistoBueno())
				listaVistoBueno.add(info);
			else
				listaPendientes.add(info);
		}
		
		setListaReparacionesPendientesVehiculo(listaPendientes);
		setListaReparacionesVistoBuenoVehiculo(listaVistoBueno);
	}

	/**
	 * Obtiene el cliente
	 * @return actionerror
	 */
	public String displayCliente() {
		if (cliente == null) {
			addActionError("Ocurrió un error al obtener el cliente");
		}
		else {
			try {
				setReparacionesCliente(cliente);
			} catch (SQLException e) {
				addActionError("Error al obtener el listado de reparaciones: " + e.toString());
			}
		}
		
		if (hasActionErrors())
			return ERROR;
		
		return SUCCESS;
	}

	/**
	 * Devuelve el vehículo
	 * @return actionerror
	 */
	public String displayVehiculo() {
		if (vehiculo == null) {
			addActionError("Ocurrió un error al obtener el vehiculo");
		}
		else {
			try {
				setReparacionesVehiculo(vehiculo);
			} catch (SQLException e) {
				addActionError("Error al obtener el listado de reparaciones: " + e.toString());
			}
		}
		
		if (hasActionErrors())
			return ERROR;
		
		return SUCCESS;
	}
}
